#pragma once
#include "cgzITask.h"
#include <pplx/pplxtasks.h>
#include <cpprest/http_client.h>
#include <cpprest/uri.h>

using namespace web;               // Common features like URIs.
using namespace web::http;         // Common HTTP functionality.
using namespace web::http::client; // HTTP client features.

class cgzCHttpC;
using HttpCTask = std::queue<pplx::task<void>>;

enum EHTTP_C
{
    HTTPC_LOOP,
    HTTPC_GET,
    HTTPC_POST,
    HTTPC_PUT,
    HTTPC_DELETE,
    HTTPC_HEAD,
    HTTPC_OPTIONS
};

class cgzCHttpLoopC : public cgzIData
{
public:
    friend class cgzCHttpC;
    cgzCHttpLoopC();
    virtual ~cgzCHttpLoopC();

public:
    EHTTP_C m_cmd;
};

class cgzCHttpExecC : public cgzCHttpLoopC
{
public:
    friend class cgzCHttpC;
    cgzCHttpExecC(long cookid);
    virtual ~cgzCHttpExecC();

public:
    long m_cookid;

public:
    json::value m_ret;
};

class cgzCHttpGetC : public cgzCHttpExecC
{
public:
    friend class cgzCHttpC;
    cgzCHttpGetC(long cookid, const char *url, const char *uri, const std::map<std::string, std::string> &headers,const char* body);
    virtual ~cgzCHttpGetC();

private:
    std::string m_url;
    std::string m_uri;
    std::string m_body;
    std::map<std::string, std::string> m_headers;
};

class cgzCHttpPostC : public cgzCHttpExecC
{
public:
    friend class cgzCHttpC;
    cgzCHttpPostC(long cookid, const char *url, const char *uri, const std::map<std::string, std::string> &headers,const char* body);
    virtual ~cgzCHttpPostC();

private:
    std::string m_url;
    std::string m_uri;
    std::string m_body;
    std::map<std::string, std::string> m_headers;
};

class cgzCHttpPutC : public cgzCHttpExecC
{
public:
    friend class cgzCHttpC;
    cgzCHttpPutC(long cookid, const char *url, const char *uri, const std::map<std::string, std::string> &headers,const char* body);
    virtual ~cgzCHttpPutC();

private:
    std::string m_url;
    std::string m_uri;
    std::string m_body;
    std::map<std::string, std::string> m_headers;
};

class cgzCHttpDeleteC : public cgzCHttpExecC
{
public:
    friend class cgzCHttpC;
    cgzCHttpDeleteC(long cookid, const char *url, const char *uri, const std::map<std::string, std::string> &headers,const char* body);
    virtual ~cgzCHttpDeleteC();

private:
    std::string m_url;
    std::string m_uri;
    std::string m_body;
    std::map<std::string, std::string> m_headers;
};

class cgzCHttpHeadC : public cgzCHttpExecC
{
public:
    friend class cgzCHttpC;
    cgzCHttpHeadC(long cookid, const char *url, const char *uri, const std::map<std::string, std::string> &headers,const char* body);
    virtual ~cgzCHttpHeadC();

private:
    std::string m_url;
    std::string m_uri;
    std::string m_body;
    std::map<std::string, std::string> m_headers;
};

class cgzCHttpOptionsC : public cgzCHttpExecC
{
public:
    friend class cgzCHttpC;
    cgzCHttpOptionsC(long cookid, const char *url, const char *uri, const std::map<std::string, std::string> &headers,const char* body);
    virtual ~cgzCHttpOptionsC();

private:
    std::string m_url;
    std::string m_uri;
    std::string m_body;
    std::map<std::string, std::string> m_headers;
};

class cgzCHttpC : public cgzITask
{
public:
    cgzCHttpC(cgzCThreadPool *pool, const char *name, int cid);
    virtual ~cgzCHttpC();

public:
    bool run(int64_t nms) override;

public:
    void exec(cgzCHttpGetC *exec);
    void exec(cgzCHttpPostC *exec);
    void exec(cgzCHttpPutC *exec);
    void exec(cgzCHttpDeleteC *exec);
    void exec(cgzCHttpHeadC *exec);
    void exec(cgzCHttpOptionsC *exec);

protected:
    int m_cid;
    HttpCTask m_waits;
};
